﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using AgilePlannerDT.APWebservice;
using AgilePlannerDT.Data;
using AgilePlannerDT.Data.Impl;
using System.Windows.Media;

namespace AgilePlannerDT.Utils
{
    /// <summary>
    /// Converts between planning objects and their web service counterparts
    /// </summary>
    public class PlanningObjectConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType.Equals(typeof(wsIteration)) ||
                sourceType == typeof(wsBacklog) ||
                sourceType == typeof(wsProject) ||
                sourceType == typeof(wsStoryCard) ||
                sourceType == typeof(wsLegend))
            {
                return true;
            }

            return base.CanConvertFrom(context, sourceType);
        }

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(Project) ||
                destinationType == typeof(Iteration) ||
                destinationType == typeof(Backlog) ||
                destinationType == typeof(StoryCard) ||
                destinationType == typeof(Legend))
            {
                return true;
            }

            return base.CanConvertTo(context, destinationType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value is wsProject)
                return ToProject((wsProject)value);
            else if (value is wsIteration)
                return ToIteration((wsIteration)value);
            else if (value is wsBacklog)
                return ToBacklog((wsBacklog)value);
            else if (value is wsStoryCard)
                return ToStoryCard((wsStoryCard)value);
            else if (value is wsLegend)
                return ToLegend((wsLegend)value);

            return base.ConvertFrom(context, culture, value);
        }

        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            if (value is Project)
                return ToWsProject((Project)value);
            else if (value is Iteration)
                return ToWsIteration((Iteration)value);
            else if (value is Backlog)
                return ToWsBacklog((Backlog)value);
            else if (value is StoryCard)
                return ToWsStoryCard((StoryCard)value);
            else if (value is Legend)
                return ToWsLegend((Legend)value);

            return base.ConvertTo(context, culture, value, destinationType);
        }

        #region Object conversions

        private Legend ToLegend(wsLegend legend)
        {
            return new LegendDataObject(legend.aqua, legend.blue, legend.gray, legend.green,
                legend.khaki, legend.peach, legend.pink, legend.red, legend.white, legend.yellow);
        }

        private wsLegend ToWsLegend(Legend legend)
        {
            wsLegend lgnd = new wsLegend();
            lgnd.aqua = legend.Aqua;
            lgnd.blue = legend.Blue;
            lgnd.gray = legend.Gray;
            lgnd.green = legend.Green;
            lgnd.khaki = legend.Khaki;
            lgnd.peach = legend.Peach;
            lgnd.pink = legend.Pink;
            lgnd.red = legend.Red;
            lgnd.white = legend.White;
            lgnd.yellow = legend.Yellow;

            return lgnd;
        }

        public wsStoryCard ToWsStoryCard(StoryCard storycard)
        {
            wsStoryCard sc = new wsStoryCard();
            sc.acceptanceTestText = storycard.AcceptanceTestText;
            sc.acceptanceTestUrl = storycard.AcceptanceTestUrl;
            sc.actualEffort = storycard.ActualEffort;
            sc.bestCaseEstimate = storycard.BestCaseEstimate;
            sc.color = (string)new CardColorConverter().ConvertTo(storycard.Background, typeof(string)); //Util.PredefinedColorToString(storycard.Background);
            sc.currentSideUp = storycard.CurrentSideUp;
            sc.description = storycard.Description;
            sc.handwritingImage = storycard.HandwritingImage;
            sc.height = (int)storycard.Height;
            sc.id = storycard.ID;
            sc.locationX = (int)storycard.LocationX;
            sc.locationY = (int)storycard.LocationY;
            sc.mostlikelyEstimate = storycard.MostlikelyEstimate;
            sc.name = storycard.Name;
            sc.ownerField = storycard.CardOwner;
            sc.parent = storycard.Parent;
            sc.rotationAngle = (float)storycard.RotationAngle;
            sc.status = storycard.Status;
            sc.width = (int)storycard.Width;
            sc.worstCaseEstimate = storycard.WorstCaseEstimate;
            return sc;
        }

        public wsIteration ToWsIteration(Iteration iteration)
        {
            wsIteration iter = new wsIteration();
            iter.actualEffort = iteration.ActualEffort;
            iter.availableEffort = iteration.AvailableEffort;
            iter.bestCaseEstimate = iteration.BestCaseEstimate;
            iter.description = iteration.Description;
            iter.endDate = iteration.EndDate;

            //don't forget to set this to true or the date
            //will not be sent via the webservice!
            iter.endDateSpecified = true;

            iter.height = (int)iteration.Height;
            iter.id = iteration.ID;
            iter.locationX = (int)iteration.LocationX;
            iter.locationY = (int)iteration.LocationY;
            iter.mostlikelyEstimate = iteration.MostlikelyEstimate;
            iter.name = iteration.Name;
            iter.parent = iteration.Parent;
            iter.startDate = iteration.StartDate;

            //don't forget to set this to true or the date
            //will not be sent via the webservice!
            iter.startDateSpecified = true;
            iter.status = iteration.Status;
            iter.width = (int)iteration.Width;
            iter.worstCaseEstimate = iteration.WorstCaseEstimate;

            wsStoryCard[] storycards = new wsStoryCard[iteration.StoryCardChildren.Count];
            int i = 0;

            foreach (StoryCard sc in iteration.StoryCardChildren)
            {
                storycards[i] = ToWsStoryCard(sc);
                i++;
            }

            iter.storyCardChildren = storycards;

            return iter;

        }

        public wsProject ToWsProject(Project project)
        {
            wsProject prj = new wsProject();
            prj.backlog = ToWsBacklog(project.Backlog);

            wsIteration[] iterations = new wsIteration[project.IterationChildren.Count];
            int i = 0;

            foreach (Iteration iteration in project.IterationChildren)
            {
                iterations[i] = ToWsIteration(iteration);
                i++;
            }

            prj.iterationChildren = iterations;
            return prj;
        }

        public wsBacklog ToWsBacklog(Backlog backlog)
        {
            wsBacklog back = new wsBacklog();
            back.actualEffort = backlog.ActualEffort;
            back.availableEffort = backlog.AvailableEffort;
            back.bestCaseEstimate = backlog.BestCaseEstimate;
            back.description = backlog.Description;
            back.endDate = backlog.EndDate;

            //don't forget to set this to true or the date
            //will not be sent via the webservice!
            back.endDateSpecified = true;

            back.height = (int)backlog.Height;
            back.id = backlog.ID;
            back.locationX = (int)backlog.LocationX;
            back.locationY = (int)backlog.LocationY;
            back.mostlikelyEstimate = backlog.MostlikelyEstimate;
            back.name = backlog.Name;
            back.parent = backlog.Parent;
            back.startDate = backlog.StartDate;

            //don't forget to set this to true or the date
            //will not be sent via the webservice!
            back.startDateSpecified = true;

            back.status = backlog.Status;
            back.width = (int)backlog.Width;
            back.worstCaseEstimate = backlog.WorstCaseEstimate;

            wsStoryCard[] storycards = new wsStoryCard[backlog.StoryCardChildren.Count];
            int i = 0;

            foreach (StoryCard sc in backlog.StoryCardChildren)
            {
                storycards[i] = ToWsStoryCard(sc);
                i++;
            }

            back.storyCardChildren = storycards;

            return back;
        }

        public StoryCard ToStoryCard(wsStoryCard storycard)
        {
            StoryCard sc = new StoryCardDataObject();
            sc.AcceptanceTestText = CheckStringForNull(storycard.acceptanceTestText);
            sc.AcceptanceTestUrl = CheckStringForNull(storycard.acceptanceTestUrl);
            sc.ActualEffort = storycard.actualEffort;
            sc.Background = (Color)new CardColorConverter().ConvertFrom(storycard.color);//Util.PredefinedStringToColor(storycard.color);
            sc.BestCaseEstimate = storycard.bestCaseEstimate;
            sc.CardOwner = CheckStringForNull((storycard.ownerField));
            sc.CurrentSideUp = storycard.currentSideUp;
            sc.Description = CheckStringForNull(storycard.description);
            sc.HandwritingImage = CheckByteArrayForNull(storycard.handwritingImage);
            sc.Height = storycard.height;
            sc.ID = storycard.id;
            sc.LocationX = storycard.locationX;
            sc.LocationY = storycard.locationY;
            sc.MostlikelyEstimate = storycard.mostlikelyEstimate;
            sc.Name = CheckStringForNull(storycard.name);
            sc.Parent = storycard.parent;
            sc.RotationAngle = storycard.rotationAngle;
            sc.Status = CheckStringForNull(storycard.status);
            sc.Width = storycard.width;
            sc.WorstCaseEstimate = storycard.worstCaseEstimate;

            return sc;
        }

        public Iteration ToIteration(wsIteration iteration)
        {
            Iteration iter = new IterationDataObject();
            iter.ActualEffort = iteration.actualEffort;
            iter.AvailableEffort = iteration.availableEffort;
            iter.BestCaseEstimate = iteration.bestCaseEstimate;
            iter.Description = iteration.description;
            iter.EndDate = iteration.endDate;
            iter.Height = iteration.height;
            iter.ID = iteration.id;
            iter.LocationX = iteration.locationX;
            iter.LocationY = iteration.locationY;
            iter.MostlikelyEstimate = iteration.mostlikelyEstimate;
            iter.Name = iteration.name;
            iter.Parent = iteration.parent;
            iter.StartDate = iteration.startDate;
            iter.Status = iteration.status;
            iter.Width = iteration.width;
            iter.WorstCaseEstimate = iteration.worstCaseEstimate;

            List<StoryCard> storycards = new List<StoryCard>();

            if (iteration.storyCardChildren != null)
            {
                foreach (wsStoryCard storycard in iteration.storyCardChildren)
                    storycards.Add(ToStoryCard(storycard));
            }

            iter.StoryCardChildren = storycards;

            return iter;
        }

        public Project ToProject(wsProject project)
        {
            Project prj = new ProjectDataObject();

            prj.ID = project.id;
            prj.Name = project.name;

            //LegendDataObject legend = project.legend;

            //prj.Legend = new LegendDataObject(legend.aqua, legend.blue, legend.gray, legend.green,
            //    legend.khaki, legend.peach, legend.pink, legend.red, legend.white, legend.yellow);

            prj.Legend = (Legend)new PlanningObjectConverter().ConvertFrom(project.legend);

            if (project.backlog != null)
            {
                prj.Backlog = ToBacklog(project.backlog);
            }

            List<Iteration> iterations = new List<Iteration>();

            if (project.iterationChildren != null)
            {
                if (project.iterationChildren.Length > 0)
                {
                    foreach (wsIteration iter in project.iterationChildren)
                        iterations.Add(ToIteration(iter));
                }
            }

            prj.IterationChildren = iterations;

            return prj;
        }

        /// <summary>
        /// Converts wsBacklog to Backlog
        /// </summary>
        /// <param name="backlog">wsBacklog to convert</param>
        /// <returns>Converted Backlog</returns>
        public Backlog ToBacklog(wsBacklog backlog)
        {
            Backlog back = new BacklogDataObject();
            back.ActualEffort = backlog.actualEffort;
            back.AvailableEffort = backlog.availableEffort;
            back.BestCaseEstimate = backlog.bestCaseEstimate;
            back.Description = backlog.description;
            back.Height = backlog.height;
            back.ID = backlog.id;
            back.LocationX = backlog.locationX;
            back.LocationY = backlog.locationY;
            back.MostlikelyEstimate = backlog.mostlikelyEstimate;
            back.Name = backlog.name;
            back.Parent = backlog.parent;
            back.Status = backlog.status;
            back.Width = backlog.width;
            back.WorstCaseEstimate = backlog.worstCaseEstimate;

            List<StoryCard> storycards = new List<StoryCard>();

            if (backlog.storyCardChildren != null)
            {
                foreach (wsStoryCard storycard in backlog.storyCardChildren)
                    storycards.Add(ToStoryCard(storycard));
            }

            back.StoryCardChildren = storycards;

            return back;
        }

        private String CheckStringForNull(String str)
        {
            if (str == null)
                return "";
            else
                return str;
        }

        private byte[] CheckByteArrayForNull(byte[] ba)
        {
            if (ba == null)
                return new byte[0];
            else
                return ba;
        }

        #endregion
    }
}
